#include "Kvstore.h"
#include <stdio.h>

#define KVSTORE_MAX_TOKENS 128

const char *commands[] = {
    "SET","GET","DEL","MOD","COUNT",
    "RSET","RGET","RDEL","RMOD","RCOUNT"
};

enum {
    KVS_CMD_START = 0,
    KVS_CMD_SET = KVS_CMD_START,
    KVS_CMD_GET,
    KVS_CMD_DEL,
    KVS_CMD_MOD,
    KVS_CMD_COUNT,
    KVS_CMD_RSET,
    KVS_CMD_RGET,
    KVS_CMD_RDEL,
    KVS_CMD_RMOD,
    KVS_CMD_RCOUNT,
    KVS_CMD_SIZE,
};

void *kvstore_malloc(size_t size){
#if ENABLE_MEM_POOL
    return mp_alloc(&m);
#else
    return malloc(size);
#endif
}

void kvstore_free(void *ptr){
#if ENABLE_MEM_POOL
    return mp_free(&m,ptr);
#else
    return free(ptr);
#endif
}

#if ENABLE_RBTREE_KVENGINE

int kvstore_rbtree_set(char *key,char *value){
    return kvs_rbtree_set(&Tree, key, value);
}
char * kvstore_rbtree_get(char *key){
    return kvs_rbtree_get(&Tree , key);
}
int kvstore_rbtree_delete(char *key){
    return kvs_rbtree_delete(&Tree , key);
}
int kvstore_rbtree_modify(char *key, char *value){
    return kvs_rbtree_modify(&Tree, key, value);
}
int kvstore_rbtree_count(){
    return kvs_rbtree_count(&Tree);
}

#endif

#if ENABLE_ARRAY_KVENGINE

int kvstore_array_set(char *key,char *value){
    return kvs_array_set(&Array, key, value);
}
char * kvstore_array_get(char *key){
    return kvs_array_get(&Array , key);
}
int kvstore_array_delete(char *key){
    return kvs_array_delete(&Array , key);
}
int kvstore_array_modify(char *key, char *value){
    return kvs_array_modify(&Array, key, value);
}
int kvstore_array_count(){
    return kvs_array_count(&Array);
}


#endif

int kvstore_split_token(char *msg, char **tokens){
    if(msg == NULL || tokens == NULL){
        return -1;
    }
    int idx = 0;

    char *token = strtok(msg, " ");

    while(token != NULL){
        tokens[idx++] = token;
        token = strtok(NULL, " ");
    }
    return idx;
}

int kvstore_parse_protocol(struct conn_item *item, char **tokens, int count){
    if(item == NULL || tokens[0] == NULL || count == 0){
        return -1;
    }

    int cmd = KVS_CMD_START;
    for(cmd = KVS_CMD_START; cmd < KVS_CMD_SIZE; cmd++){
        if(strcmp(commands[cmd], tokens[0]) == 0){
            break;
        }
    }

    char *msg = item->wbuffer;
    char *key = tokens[1];
    char *value = tokens[2];
    memset(msg, 0, BUFFER_LENGTH);

    switch (cmd) {
        case KVS_CMD_SET:{
            int ret = kvstore_array_set(key,value);
            if(!ret){
                snprintf(msg, BUFFER_LENGTH, "SUCCESS");
            }else {
                snprintf(msg, BUFFER_LENGTH, "FAILED");
            }
            LOG("set: %d\n",ret);

            break;
        }
        case KVS_CMD_GET:{
            char *val = kvstore_array_get(key);
            if(val){
                snprintf(msg, BUFFER_LENGTH, "%s",val);
            }else {
                snprintf(msg, BUFFER_LENGTH, "NO EXIST");
            }
            LOG("get: %s\n",val);

            break;
        }
        case KVS_CMD_DEL:{
            LOG("del\n");

            int ret = kvstore_array_delete(key);
            if(ret < 0){
                snprintf(msg, BUFFER_LENGTH, "%s","ERROR");
            }else if (ret == 0) {
                snprintf(msg, BUFFER_LENGTH, "%s","SUCCESS");
            }else {
                snprintf(msg, BUFFER_LENGTH, "NO EXIST");
            }

            break;
        }
        case KVS_CMD_MOD:{
            LOG("mod\n");

            int ret = kvstore_array_modify(key,value);
            if(ret < 0){
                snprintf(msg, BUFFER_LENGTH, "%s","ERROR");
            }else if (ret == 0) {
                snprintf(msg, BUFFER_LENGTH, "%s","SUCCESS");
            }else {
                snprintf(msg, BUFFER_LENGTH, "NO EXIST");
            }
            break;
        }
        case KVS_CMD_COUNT:{
            int count = kvstore_array_count();
            if(count < 0){
                snprintf(msg, BUFFER_LENGTH, "%s","ERROR");
            }
            else {
                snprintf(msg, BUFFER_LENGTH, "%d",count);
            }
            break;
        }
        case KVS_CMD_RSET:{
            int ret = kvstore_rbtree_set(key,value);
            if(!ret){
                snprintf(msg, BUFFER_LENGTH, "SUCCESS");
            }else {
                snprintf(msg, BUFFER_LENGTH, "FAILED");
            }
            LOG("rset: %s\n", key);
            break;
        }
        case KVS_CMD_RGET:{
            char *val = kvstore_rbtree_get(key);
            if(val){
                snprintf(msg, BUFFER_LENGTH, "%s",val);
            }else {
                snprintf(msg, BUFFER_LENGTH, "NO EXIST");
            }
            LOG("rget: %s\n", key);
            break;
        }
        case KVS_CMD_RDEL:{
            int ret = kvstore_rbtree_delete(key);
            if(ret < 0){
                snprintf(msg, BUFFER_LENGTH, "%s","ERROR");
            }else if (ret == 0) {
                snprintf(msg, BUFFER_LENGTH, "%s","SUCCESS");
            }else {
                snprintf(msg, BUFFER_LENGTH, "NO EXIST");
            }
            LOG("rdel: %s\n", key);
            break;
        }
        case KVS_CMD_RMOD:{
            int ret = kvstore_rbtree_modify(key,value);
            if(ret < 0){
                snprintf(msg, BUFFER_LENGTH, "%s","ERROR");
            }else if (ret == 0) {
                snprintf(msg, BUFFER_LENGTH, "%s","SUCCESS");
            }else {
                snprintf(msg, BUFFER_LENGTH, "NO EXIST");
            }
            LOG("rmod: %s\n", key);
            break;
        }
        case KVS_CMD_RCOUNT:{
            int count = kvstore_rbtree_count();
            if(count < 0){
                snprintf(msg, BUFFER_LENGTH, "%s","ERROR");
            }
            else {
                snprintf(msg, BUFFER_LENGTH, "%d",count);
            }
            break;
        }
        default:{
            LOG("cmd: %s\n",commands[cmd]);
            assert(0);
        }
    }
    return 0;
}

int kvstore_request(struct conn_item *item){
    LOG("recv: %s\n",item->rbuffer);

    char *msg = item->rbuffer;
    char *tokens[KVSTORE_MAX_TOKENS];
    
    int count = kvstore_split_token(msg, tokens);
    int idx = 0;
    for(idx = 0; idx < count; idx++){
        LOG("idx: %s\n",tokens[idx]);
    }

    kvstore_parse_protocol(item, tokens, count);
    return 0;
}

int kvstore_response(){
    return 0;
}

int init_kvengine(){
#if ENABLE_ARRAY_KVENGINE
    kvstore_array_create(&Array);
#endif

#if ENABLE_RBTREE_KVENGINE
    kvstore_rbtree_create(&Tree);
#endif

    return 0;
}

int exit_kvengine(){
#if ENABLE_ARRAY_KVENGINE
    kvstore_array_destory(&Array);
#endif

#if ENABLE_RBTREE_KVENGINE
    kvstore_rbtree_destory(&Tree);
#endif

    return 0;
}

int init_ctx(){
#if ENABLE_MEM_POOL
    mp_init(&m, 40960);
#endif
    return 0;
}

int dest_ctx(){
#if ENABLE_MEM_POOL
    mp_dest(&m);
#endif
    return 0;
}

int main(){

    init_ctx();
    init_kvengine();

#if (ENABLE_NETWORK_SELECT == NETWORK_EOPLL)
    epoll_entry();
#elif (ENABLE_NETWORK_SELECT == NETWORK_NTYCO)
    ntyco_entry();
#elif (ENABLE_NETWORK_SELECT == NETWORK_IOURING)

#endif

    exit_kvengine();
    dest_ctx();
}